package br.com.hs.nfe.common.util.io;

import java.io.IOException;
import java.io.InputStream;
import java.io.PushbackInputStream;

/**
 * Classe de implementação de InputStream.
 * @author Ranlive Hrysyk
 */
public class UnicodeInputStream extends InputStream {

    PushbackInputStream in;
    boolean open = false;
    String defaultEnc;
    String encoding;

    /**
     * Construtor da classe.
     */
    public UnicodeInputStream(InputStream in, String defaultEnc) {
        this.in = new PushbackInputStream(in, 4);
        this.defaultEnc = defaultEnc;
    }

    /**
     * Obtém o encoding default.
     */
    public String getDefaultEncoding() {
        return this.defaultEnc;
    }

    /**
     * Obtém o encoding.
     */
    public String getEncoding() {
        if (!this.open) {
            try {
                init();
            } catch (IOException ex) {
                throw new IllegalStateException("Init method failed.", ex);
            }
        }
        return this.encoding;
    }

    private void init() throws IOException {
        if (this.open) {
            return;
        }
        byte[] bom = new byte[4];
        int n = this.in.read(bom, 0, bom.length);
        int unread = 0;
        if ((bom[0] == 0) && (bom[1] == 0) && (bom[2] == -2) && (bom[3] == -1)) {
            this.encoding = "UTF-32BE";
            unread = n - 4;
        } else {
            if ((bom[0] == -1) && (bom[1] == -2) && (bom[2] == 0) && (bom[3] == 0)) {
                this.encoding = "UTF-32LE";
                unread = n - 4;
            } else {
                if ((bom[0] == -17) && (bom[1] == -69) && (bom[2] == -65)) {
                    this.encoding = "UTF-8";
                    unread = n - 3;
                } else {
                    if ((bom[0] == -2) && (bom[1] == -1)) {
                        this.encoding = "UTF-16BE";
                        unread = n - 2;
                    } else {
                        if ((bom[0] == -1) && (bom[1] == -2)) {
                            this.encoding = "UTF-16LE";
                            unread = n - 2;
                        } else {
                            this.encoding = this.defaultEnc;
                            unread = n;
                        }
                    }
                }
            }
        }
        if (unread > 0) {
            this.in.unread(bom, n - unread, unread);
        }
        this.open = true;
    }

    @Override
    public void close() throws IOException {
        this.open = true;
        this.in.close();
    }

    @Override
    public int read() throws IOException {
        this.open = true;
        return this.in.read();
    }
}
